#include "ThrowItem.h"

#include "../CommandManager.h"
#include "../GameObjects/Room.h"
#include "../GameObjects/Character.h"
#include "../GameObjects/Item.h"
#include "../Player.h"
#include "../Components/Vitality.h"
#include "../Components/Weapon.h"
#include "../Components/Blade.h"

#include "../StringHelper.h"

#include <iostream>

void ThrowItem::Init()
{
	CommandManager::getSingleton()->add(std::make_shared<Throw>());
}

///////////////////////////////////////
// HOLD ITEM
///////////////////////////////////////
Throw::Throw() : Command("throw")
{
	add("thr");
}
void Throw::execute(const CharacterPtr &character, const RoomPtr &room, const std::vector<std::string> &args)
{
	//Throw held item
	if(args.empty())
	{
		ItemPtr item = character->removeItemInHand();
		if(item)
		{
			room->add(item);
			item->setStance(Item::LAYING);
			if(character->hasPlayer())
				std::cout << "You throw the " << item->getName() << " on the ground." << std::endl;
			else
				std::cout << character->getName() << " throws " << item->getIndefiniteArticle() << " " << item->getName() << " on the ground." << std::endl;
		}
		else if(character->hasPlayer())
		{
				std::cout << "You're not holding anything!" << std::endl;
		}
	}

	//Throw a named, held item
	else if(args.size() == 1)
	{
		if(character->getHeldItem())
		{
			if(character->getHeldItem()->is(args[0]))
			{
				ItemPtr item = character->removeItemInHand();
				room->add(item);
				item->setStance(Item::LAYING);
				if(character->hasPlayer())
					std::cout << "You throw the " << item->getName() << " on the ground." << std::endl;
				else
					std::cout << character->getName() << " throws " << item->getIndefiniteArticle() << " "<< item->getName() << " on the ground." << std::endl;
			}
			else if(character->hasPlayer())
			{
				std::cout << "You can't throw what you're not holding." << std::endl;
			}
		}
		else if(character->hasPlayer())
		{
				std::cout << "You're not holding anything!" << std::endl;
		}
	}

	//Throw held item at someone...
	else if(args.size() == 2)
	{
		if(character->getHeldItem())
		{
			if(args[0] == "at")
			{
				//Check if we're trying to throw at a character in the room
				for(unsigned int i = 0; i < room->getCharacters().size(); i++)
				{
					if(room->getCharacters()[i]->is(args[1]))
					{
						//Are we trying to hit ourselves?
						if(room->getCharacters()[i]->getName() == character->getName())
						{
							if(character->hasPlayer())
								std::cout << "Now that would be an interesting experiment..." << std::endl;
						}
						//Else we throw at the character
						else
						{
							const CharacterPtr &target = room->getCharacters()[i];
							ItemPtr item = character->removeItemInHand();

							if(character->hasPlayer())
								std::cout << "You throw the " << item->getName() << " at " << target->getIndefiniteArticle() << " " << target->getName() << std::endl;
							else if(target->hasPlayer())
								std::cout << character->getName() << " throws " << item->getIndefiniteArticle() << " "<< item->getName() << " at you!" << std::endl;
							else
								std::cout << character->getName() << " throws " << item->getIndefiniteArticle() << " "<< item->getName() << " at " << target->getIndefiniteArticle() << " " << target->getName() << std::endl;

							// Really bad damage formulae
							int dmg = 0;
							if(item->hasComponent("Weapon"))
							{
								if(item->hasComponent("Blade"))
									dmg = item->getComponent<Weapon>("Weapon")->calcDamage(Weapon::STAB); //Throwing knives, etc
								else
									dmg = item->getComponent<Weapon>("Weapon")->calcDamage(Weapon::BLUNT); //Throwing stones, etc
							}
							
							//For now every character is equally strong... but stats like that could affect the throw
							if(target->hasComponent("Vitality"))
							{
								Character::BodyPart bodypart = target->getRandomBodypart();
								target->getComponent<Vitality>("Vitality")->damage(target, bodypart, dmg, room);
							}
							else
							{
								if(target->hasPlayer())
									std::cout << "You're unaffected!" << std::endl;
								else
									std::cout << StringHelper::toUpper(target->getIndefiniteArticle()) << " " << target->getName() << " seems unaffected!" << std::endl;
							}

							//After hitting it's target, the item falls on the ground...
							room->add(item);
							item->setStance(Item::LAYING);
						}
						return;
					}
				}
				if(character->hasPlayer())
					std::cout << "Throw at whom?" << std::endl;
			}
			else if(character->hasPlayer())
			{
				std::cout << "And how are you supposed to do that?" << std::endl;
			}
		}
		else if(character->hasPlayer())
		{
				std::cout << "You're not holding anything!" << std::endl;
		}
	}

	//Throw named, held item at someone...
	else if(args.size() == 3)
	{
 		if(character->getHeldItem())
		{
			if(character->getHeldItem()->is(args[0]))
			{
				if(args[1] == "at")
				{
					//Check if we're trying to throw at a character in the room
					for(unsigned int i = 0; i < room->getCharacters().size(); i++)
					{
						if(room->getCharacters()[i]->is(args[2]))
						{
							//Are we trying to hit ourselves?
							if(room->getCharacters()[i]->getName() == character->getName())
							{
								if(character->hasPlayer())
									std::cout << "Now that would be an interesting experiment..." << std::endl;
							}
							//Else we throw at the character
							else
							{
								const CharacterPtr &target = room->getCharacters()[i];
								ItemPtr item = character->removeItemInHand();

								if(character->hasPlayer())
									std::cout << "You throw the " << item->getName() << " at " << target->getIndefiniteArticle() << " " << target->getName() << std::endl;
								else if(target->hasPlayer())
									std::cout << character->getName() << " throws " << item->getIndefiniteArticle() << " "<< item->getName() << " at you!" << std::endl;
								else
									std::cout << character->getName() << " throws " << item->getIndefiniteArticle() << " "<< item->getName() << " at " << target->getIndefiniteArticle() << " " << target->getName() << std::endl;

								// Really bad damage formulae
								int dmg = 0;
								if(item->hasComponent("Weapon"))
								{
									if(item->hasComponent("Blade"))
										dmg = item->getComponent<Weapon>("Weapon")->calcDamage(Weapon::STAB); //Throwing knives, etc
									else
										dmg = item->getComponent<Weapon>("Weapon")->calcDamage(Weapon::BLUNT); //Throwing stones, etc
								}
							
								//For now every character is equally strong... but stats like that could affect the throw
								if(target->hasComponent("Vitality"))
								{
									Character::BodyPart bodypart = target->getRandomBodypart();
									target->getComponent<Vitality>("Vitality")->damage(target, bodypart, dmg, room);
								}
								else
								{
									if(target->hasPlayer())
										std::cout << "You're unaffected!" << std::endl;
									else
										std::cout << StringHelper::toUpper(target->getIndefiniteArticle()) << " " << target->getName() << " seems unaffected!" << std::endl;
								}

								//After hitting it's target, the item falls on the ground...
								room->add(item);
								item->setStance(Item::LAYING);
							}
							return;
						}
					}
					if(character->hasPlayer())
						std::cout << "Throw at whom?" << std::endl;
				}
				else if(character->hasPlayer())
				{
					std::cout << "And how are you supposed to do that?" << std::endl;
				}
			}
			else if(character->hasPlayer())
			{
				std::cout << "You can't throw what you're not holding." << std::endl;
			}
		}
		else if(character->hasPlayer())
		{
				std::cout << "You're not holding anything!" << std::endl;
		}
	}
	else if(character->hasPlayer())
	{
		std::cout << "You don't know how to do that!" << std::endl;
	}
}
